home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / disk / zerofile.zip / ZEROFILE.MOD < prev    next >
Text File  |  1993-06-16  |  6KB  |  220 lines

  1. MODULE Zerofile;
  2.  
  3. IMPORT FIO, Lib, Str;
  4. FROM IO IMPORT WrStr, WrLn;
  5.  
  6. TYPE
  7.   PathType = ARRAY [0..80] OF CHAR;
  8. VAR
  9.   verbose, recursive_scan: BOOLEAN;
  10.   errorlevel: SHORTCARD;
  11.   path: PathType;
  12.  
  13. PROCEDURE Wr( s: ARRAY OF CHAR );
  14.   BEGIN
  15.     WrStr( s );
  16.     WrLn
  17.   END Wr;
  18.  
  19. PROCEDURE Banner;
  20.   BEGIN
  21.     Wr('Zerofile - by P. Below, 1993, Freeware');
  22.     Wr('- Search a directory for files of zero length - ');
  23.     WrLn;
  24.   END Banner;
  25.  
  26. PROCEDURE Usage;
  27.   BEGIN
  28.     Banner;
  29.     Wr('Usage: zerofile [pathname] [/S] [/Q] [/?]');
  30.     WrLn;
  31.     Wr('pathname is either the name of a directory or a filespec. If the latter,');
  32.     Wr('the filename part may contain wildcards. If pathname is omitted, zerofile');
  33.     Wr('will search the current drive.');
  34.     WrLn;
  35.     Wr('Switches:');
  36.     Wr('  /S : search recursively through all subdirectories, if pathname is');
  37.     Wr('       a directory.');
  38.     Wr('  /Q : quiet, do not display anything on screen.');
  39.     Wr('  /? or any other switch will yield this information.');
  40.     WrLn;
  41.     Wr('Zerofile will return errorlevel 1 if a file with zero length is found,');
  42.     Wr('errorlevel 255 if it gets an invalid pathname and 0 otherwise.');
  43.   END Usage;
  44.  
  45. PROCEDURE GetCurrentPath( VAR path: ARRAY OF CHAR );
  46.   VAR
  47.     drive: ARRAY [0..2] OF CHAR;
  48.   BEGIN
  49.     drive[0] := CHR( FIO.GetDrive() - 1 + SHORTCARD('A'));
  50.     drive[1] := ':';
  51.     FIO.GetDir( 0, path );
  52.     IF path[0] # '\' THEN
  53.       drive[2] := '\'
  54.     ELSE
  55.       drive[2] := 0C
  56.     END;
  57.     Str.Prepend( path, drive );
  58.   END GetCurrentPath;
  59.  
  60. PROCEDURE Truncate( VAR path: PathType );
  61.   VAR i: CARDINAL;
  62.   BEGIN
  63.     (* remove the filename part from path *)
  64.     i := Str.Length( path );
  65.     LOOP
  66.       IF i = 0 THEN EXIT END;
  67.       DEC( i );
  68.       IF (path[i] = ':') OR (path[i] = '\') THEN EXIT END;
  69.       path[i] := 0C;
  70.     END
  71.   END Truncate;
  72.  
  73. PROCEDURE DotDir( name: FIO.PathTail ): BOOLEAN;
  74.   (* returns true, id name is either '.' or '..'. Modula-2 cannot
  75.      compare an array of char to a char because these are not compatible
  76.      types! *)
  77.   BEGIN
  78.     RETURN (name[0] = '.') AND ((name[1] = 0C) OR (name[1] = '.'));
  79.   END DotDir;
  80.  
  81. PROCEDURE ScanParams;
  82.   VAR
  83.     i   : CARDINAL;
  84.     str : PathType;
  85.   BEGIN
  86.     FOR i := 1 TO Lib.ParamCount() DO
  87.       Lib.ParamStr( str, i );     (* get parameter *)
  88.       Str.Caps( str );            (* convert to upper case *)
  89.       IF str[0] = '/' THEN        (* test for switch *)
  90.         CASE str[1] OF            (* evaluate switch *)
  91.           'S' : recursive_scan := TRUE;
  92.         | 'Q' : verbose := FALSE;
  93.         ELSE
  94.           (* anything else gives the help info and terminates *)
  95.           Usage;
  96.           errorlevel := 255;
  97.           RETURN
  98.         END;
  99.       ELSE
  100.         (* anything not a switch is taken to be a pathname *)
  101.         path := str;
  102.       END;
  103.     END; (* FOR *)
  104.   END ScanParams;
  105.  
  106. PROCEDURE ScanForZerofiles ( VAR path: PathType );
  107.   VAR
  108.     dir : FIO.DirEntry;
  109.     done: BOOLEAN;
  110.   BEGIN
  111.     done := NOT FIO.ReadFirstEntry( path, FIO.FileAttr{}, dir );
  112.     IF FIO.IOresult() <> 0 THEN
  113.       (* invalid pathname. give error message if verbose mode *)
  114.       IF verbose THEN
  115.         WrStr('Invalid pathname: ');
  116.         Wr( path );
  117.       END;
  118.       errorlevel := 255;
  119.       done := TRUE
  120.     END;
  121.  
  122.     WHILE NOT done DO
  123.       IF dir.size = 0 THEN
  124.         errorlevel := 1;
  125.         IF verbose THEN
  126.           Truncate( path );
  127.           WrStr( path );
  128.           WrStr( dir.Name );
  129.           Wr(' has zero bytes length.');
  130.         END;
  131.         done := TRUE
  132.       ELSE
  133.         done := NOT FIO.ReadNextEntry( dir );
  134.       END;
  135.     END; (* WHILE *)
  136.   END ScanForZerofiles;
  137.  
  138. PROCEDURE ScanDirectory( path: PathType );
  139.   VAR
  140.     dir : FIO.DirEntry;
  141.     done: BOOLEAN;
  142.   BEGIN
  143.     (* path has a directory name, append wildcard *.* filespec for scan *)
  144.     IF path[Str.Length(path)-1] <> '\' THEN
  145.       Str.Append( path, '\' )
  146.     END;
  147.     Str.Append( path, '*.*' );
  148.  
  149.     (* scan directory for zero byte files *)
  150.     ScanForZerofiles( path );
  151.  
  152.     (* if we did not find any and recursive scan was requested, search for
  153.        subdirectories and scan any found *)
  154.     IF recursive_scan AND (errorlevel = 0) THEN
  155.       done := NOT FIO.ReadFirstEntry( path, FIO.FileAttr{FIO.directory},
  156.                                       dir );
  157.  
  158.       WHILE NOT done DO
  159.         IF (FIO.directory IN dir.attr) AND NOT DotDir(dir.Name) THEN
  160.           (* found a subdirectory. remove *.* from path and add the subdirs
  161.              name instead; then call this procedure recursively *)
  162.           Truncate( path );
  163.           Str.Append( path, dir.Name );
  164.           ScanDirectory( path );
  165.         END;
  166.         IF errorlevel = 0 THEN
  167.           done := NOT FIO.ReadNextEntry( dir )
  168.         ELSE
  169.           done := TRUE
  170.         END;
  171.       END; (* WHILE *)
  172.     END; (* IF *)
  173.   END ScanDirectory;
  174.  
  175. PROCEDURE ScanFiles( VAR path: PathType );
  176.   VAR
  177.     dir: FIO.DirEntry;
  178.   BEGIN
  179.     IF verbose THEN
  180.       Banner
  181.     END;
  182.     IF FIO.Exists( path ) THEN
  183.       (* valid filename given *)
  184.       IF FIO.ReadFirstEntry( path, FIO.FileAttr{}, dir ) AND
  185.          (dir.size = 0) THEN
  186.         errorlevel := 1;
  187.       END
  188.     ELSE
  189.       (* directory name assumed, if wildcards present, disable recursive
  190.          scan *)
  191.       IF (Str.CharPos( path, '*' ) < MAX( CARDINAL )) OR
  192.          (Str.CharPos( path, '?' ) < MAX( CARDINAL )) THEN
  193.         recursive_scan := FALSE;
  194.         ScanForZerofiles( path );
  195.       ELSE
  196.         ScanDirectory( path );
  197.       END;
  198.     END;
  199.   END ScanFiles;
  200.  
  201. BEGIN
  202.   FIO.IOcheck := FALSE;  (* don't terminate on I/O errors *)
  203.   verbose := TRUE;
  204.   recursive_scan:= FALSE;
  205.   errorlevel:= 0;
  206.   path:= '';
  207.  
  208.   ScanParams;
  209.   IF errorlevel = 0 THEN
  210.     IF Str.Length( path ) = 0 THEN
  211.       (* no path given, scan current directory *)
  212.       GetCurrentPath( path );
  213.     END;
  214.     ScanFiles( path );
  215.   END;
  216.   IF (errorlevel = 0) AND verbose THEN
  217.     Wr('No files with zero bytes length were found.');
  218.   END;
  219.   Lib.SetReturnCode( errorlevel );
  220. END Zerofile.